package org.hcf.utils.lang;

import org.apache.commons.collections4.CollectionUtils;

import java.io.ByteArrayOutputStream;
import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Stream;

/**
 * 字符串辅助工具
 *
 * @author hcf
 * @email hcf0108@163.com
 * @create 2019-02-28 下午 3:49
 **/
public class StringUtils {
    public static String fromEncode = "ISO-8859-1";
    public static String toEncode = "UTF-8";
    public static boolean encodeToCN = false;


    /**
     * 判断是否是空白字符串
     * @param string
     * @return
     */
    public static boolean isNullString(String string) {
        if(null == string || "".equals(string.trim()) || string.length() == 0)
            return true;
        return false;
    }

    /**
     * 将Null转换成空字符串
     * @param string 所要转换的字符串
     */
    public static String nullToString(String string) {
        return string == null ? "" : string;
    }

    /**
     * 对字符串进行格式化，格式化的方式为：对源字符串(sourceString)中的{n}(其中n表示数字，从0开始)
     * 进行替换，该功能类似C#中的string.Format(string s, params objs)。
     * @param sourceString 源字符串
     * @param args 所要格式化的参数信息
     * @return
     */
    public static String formater(String sourceString, Object[] args){
        if(isNullString(sourceString))
            return "";
        if(null == args || args.length == 0)
            return sourceString;
        return MessageFormat.format(sourceString, args);
    }

    /**
     * 对字符串为空时进行处理返回空值，如果不是null则返回相应的值
     *
     * @param sourceString 源字符串
     * @return
     */
    public static String formatNull(String sourceString){
        if(isNullString(sourceString))
            return "";
        return sourceString;
    }

    /**
     * 是否为真
     * @param string
     * @return
     */
    public static boolean isTrue(String string){
        if(isNullString(string))
            return false;

        string = string.trim().toUpperCase();
        if("TRUE".equalsIgnoreCase(string))
            return true;
        if("YES".equalsIgnoreCase(string))
            return true;
        if("Y".equalsIgnoreCase(string))
            return true;
        if("ON".equalsIgnoreCase(string))
            return true;
        return false;
    }

    /**
     * 是否为False
     * @param string
     * @return
     */
    public static boolean isFalse(String string){
        if(isNullString(string))
            return false;

        string = string.trim().toUpperCase();
        if("FALSE".equalsIgnoreCase(string))
            return true;
        if("NO".equalsIgnoreCase(string))
            return true;
        if("N".equalsIgnoreCase(string))
            return true;
        if("OFF".equalsIgnoreCase(string))
            return true;
        return false;
    }

    /**
     * 判断两个字符串是否相等
     * @param one
     * @param other
     * @return
     */
    public static boolean isEquals(String one, String other){
        boolean oneNull = isNullString(one);
        boolean twoNull = isNullString(other);
        if(oneNull && twoNull)
            return true;
        if((oneNull && (!twoNull)) || ((!oneNull) && twoNull))
            return false;

        if(one.equalsIgnoreCase(other))
            return true;
        return false;
    }

    /**
     * 判断是否包含
     * @param strings
     * @param string
     * @return
     */
    public static boolean isContain(String[] strings, String string) {
        if (null == strings || strings.length == 0)
            return false;

        for (int i = 0; i < strings.length; i++) {
            if (isEquals(string, strings[i]))
                return true;
        }
        return false;
    }

    /**
     * 将列表转换为字符串
     * @param sourceList 字符串列表
     * @param separator 分隔符
     * @return 组合好的字符串
     */
    public static String list2String(List sourceList, String separator) {
        if (null == sourceList || sourceList.size() < 1)
            return "";
        StringBuffer result = new StringBuffer();
        for (Iterator iter = sourceList.iterator(); iter.hasNext();) {
            String element = (String) iter.next();
            result.append(element + separator);
        }

        return result.substring(0, result.length() - separator.length());
    }



    /**
     * 将指定的字符串转换成toEncode的编码
     * @param isoString
     * @return
     */
    public static String encodingToCN(String isoString) {
        if(isNullString(isoString))
            return "";
        try {
            if(encodeToCN){
                String returnString = new String(isoString.getBytes(fromEncode), toEncode);
                return returnString;
            }else{
                return isoString;
            }
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 将指定的字符串转换成fromEncode的编码
     * @param cnString
     * @return
     */
    public static String encodingToEN(String cnString) {
        if (isNullString(cnString))
            return "";
        try {
            return new String(cnString.getBytes(toEncode), fromEncode);
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 将指定字符串的第一个字母转换成小写
     * @param sourceString 所要转换的字符串
     * @return 转换后的字符串
     */
    public static String firstCharToLowCase(String sourceString){
        if(isNullString(sourceString))
            return sourceString;
        if(sourceString.length() == 1)
            return sourceString.toLowerCase();
        return sourceString.substring(0, 1).toLowerCase() + sourceString.substring(1, sourceString.length());
    }

    /**
     * 将指定的字符串从源字符中剔除
     * @param sourceString 源字符串
     * @param trimString 所要剔除的字符串
     * @return 返回剔除后的字符串
     */
    public static String trim(String sourceString, String trimString){
        if(isNullString(sourceString))
            return "";
        if(isNullString(trimString))
            return sourceString;
        String[] temp = sourceString.split(trimString);
        if(null == temp || temp.length == 0)
            return sourceString;
        else{
            String result = "";
            for(int i = 0; i < temp.length; i++)
                result += temp[i];
            return result;
        }
    }

    /**
     * 验证字符串是否是可转换为数字格式
     * @param value 要验证的字符串
     * @return 如果输入的字符串可转换为数字格式则返回true，否则返回false
     */
    public static boolean isNumeric(String value) {
        try {
            if (isNullString(value))
                return false;
            Double.parseDouble(value);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    /*
     * 16进制数字字符集
     */
    private static String hexString = "0123456789ABCDEF";

    /*
     * 将字符串编码成16进制数字,适用于所有字符（包括中文）
     */
    public static String String2Hex(String str) {
        // 根据默认编码获取字节数组
        byte[] bytes = str.getBytes();
        StringBuffer sb = new StringBuffer(bytes.length * 2);
        // 将字节数组中每个字节拆解成2位16进制整数
        for (int i = 0; i < bytes.length; i++) {
            sb.append(hexString.charAt((bytes[i] & 0xf0) >> 4));
            sb.append(hexString.charAt((bytes[i] & 0x0f) >> 0));
        }
        return sb.toString();
    }

    /*
     * 将16进制数字解码成字符串,适用于所有字符（包括中文）
     */
    public static String Hex2String(String bytes) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream(bytes.length() / 2);

        // 将每2位16进制整数组装成一个字节
        for (int i = 0; i < bytes.length(); i += 2)
            baos.write((hexString.indexOf(bytes.charAt(i)) << 4 | hexString.indexOf(bytes.charAt(i + 1))));
        return new String(baos.toByteArray());
    }

    /**
     * 将字符串数组转换成long数组
     * @param sArray
     * @return
     */
    public static long[] stringArray2LongArray(String[] sArray){
        if(null == sArray || sArray.length == 0)
            return null;
        long[] longArray = new long[sArray.length];
        for(int i = 0; i < sArray.length; i++){
            try {
                longArray[i] = Long.parseLong(sArray[i]);
            } catch (NumberFormatException e) {
                longArray[i] = 0;
            }
        }
        return longArray;
    }

    /**
     * 将字符串数组转换成long数组
     * @param sArray
     * @return
     */
    public static long[] stringArray2LongArray(Collection sArray){
        if(null == sArray || sArray.isEmpty())
            return null;
        long[] longArray = new long[sArray.size()];
        Iterator itor = sArray.iterator();
        int i = 0;
        try {
            while(itor.hasNext()){
                longArray[i] = Long.parseLong(String.valueOf(itor.next()));
                i++;
            }
        } catch (NumberFormatException e) {
            longArray[i] = 0;
        }
        return longArray;
    }

    /**
     * 将字符串数组转换成int数组
     * @param sArray
     * @return
     */
    public static int[] stringArray2IntArray(String[] sArray){
        if(null == sArray || sArray.length == 0)
            return null;
        int[] intArray = new int[sArray.length];
        for(int i = 0; i < sArray.length; i++){
            try {
                intArray[i] = Integer.parseInt(sArray[i]);
            } catch (NumberFormatException e) {
                intArray[i] = 0;
            }
        }
        return intArray;
    }

    /**
     * 将字符串数组转换成boolean数组
     * @param sArray
     * @return
     */
    public static boolean[] stringArray2BooleanArray(String[] sArray){
        if(null == sArray || sArray.length == 0)
            return null;
        boolean[] boolArray = new boolean[sArray.length];
        for(int i = 0; i < sArray.length; i++){
            boolArray[i] = (sArray[i].equalsIgnoreCase("true"));
        }
        return boolArray;
    }

    /**
     * 合并数组中的字符串
     * @param array 要处理的数组
     * @param symbol 连接符号
     * @return 数组中各个字符串用指定符号连接
     */
    public static String join(String[] array,String symbol){
        if(Objects.isNull(array) || array.length == 0) {
            return "";
        }
        return join(Arrays.stream(array),symbol);
    }

    public static String join(Collection<String> strList, String symbol){
        if(CollectionUtils.isEmpty(strList)){
            return "";
        }
        return join(strList.stream(),symbol);
    }

    private static String join(Stream<String> strStream,String symbol){
        boolean first = true;
        StringBuffer t = new StringBuffer();
        strStream.filter(Objects::nonNull)
                .forEach(str ->{
                    t.append(symbol).append(str);
                });

        if(t.length() < 1) {
            return t.toString();
        }else {
            return t.substring(1).toString();
        }
    }
}
